# ifndef __MpsFile_H_
# define __MpsFile_H_

//
// Garmin MapSource MPS file format structure.
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2005
// Garmin and MapSource are registered trademarks or trademarks of Garmin Ltd. or one of its subsidiaries.
//
// NOTE: the code is tested for MapSource 4.09 - 6.5 only.
//

# ifdef _MSC_VER
#	pragma pack (push, 1)
# endif

	//
	// Each MPS file begins with these 6 bytes.
	//

const BYTE g_pMpsSignature [6] = {'M', 's', 'R', 'c', 'd', '\0'};

extern const BYTE g_pMpsHeader [];
extern const size_t c_cMpsHeaderSize;

extern const BYTE g_pMpsTail   [];
extern const size_t c_cMpsTailSize;


	//
	// Each record in MPS file begins with this header.
	//

struct CMpsRecordHdr {
	// Number of bytes in the record (except this header).
	DWORD dwLen;

	// Type of the record:
	// 'D' - file format version (always the first record), see CMpsFormatVersion
	// 'A' - MapSource version (always the second record), see CMpsMSVersion
	// 'V' - probably end marker (always the last record), two bytes 0x00, 0x01
	// 'W' - waypoint, see CMpsWaypointHdr, CMpsWaypoint2, CMpsWaypoint3
	// 'T' - track, see CMpsTrackHdr, CMpsTrack2, CMpsTrackPoint
	// 'R' - route
	// 'M' - map reference
	// 'V' - map collection (end of file)
	BYTE  btType;
};

	//
	// File format version.
	//

struct CMpsFormatVersion : public CMpsRecordHdr {
	// 0x64 - saved by MS ??-3.02-??
	// 0x67 - saved by MS 4.??-4.09
	// 0x68 - saved by MS 4.10-4.13
	// 0x69 - saved by MS 5.0-6.0-??
	WORD wdVersion;
};

//
// NOTE: all records defined below are applied to MPS format versions 0x67, 0x68, 0x69.
// Beginning with 0x68, non-English character are allowed in strings.
//

	//
	// MapSource version.
	//

struct CMpsMSVersion : public CMpsRecordHdr {
	// 0x012E - MapSource 3.02
	// Probably, 0x9x - MapSource 4.0x
	// 0x0199 - MapSource 4.09
	// 0x019A - MapSource 4.10
	// 0x019B - MapSource 4.11
	// 0x019C - MapSource 4.12
	// 0x019D - MapSource 4.13
	// 0x01F4 - MapSource 5.0
	// 0x01F8 - MapSource 5.4
	// 0x0258 - MapSource 6.0
	WORD wVersion;

	// Three zero-terminated strings with MapSource builder's nickname
	// and date/time of build.
	// Example: "hales\0Nov 18 2002\014:11:40\0"
	char strBuildInfo [1];
};

	//
	// Waypoint.
	//

struct CMpsWaypointHdr : public CMpsRecordHdr {
	// The label.
	char strName [1];     // Null-terminated.
};

struct CMpsWaypoint2 {
	DWORD dwClass;        // 0x00 for user waypoint

	BYTE  strCountry [1]; // ??

	DWORD dwMapSegmentID; // 0x00000000 for user waypoint. Map Segment ID for map objects. 
	DWORD dwMapObjectID;  // 0xFFFFFFFF for user waypoint. Map Object ID for map objects -
	                      // unique identifier for each road, POI, river, area, intersection, city, airport etc.

	DWORD dwSubclass10;   // Waypoint subclass for auto-routes. User waypoint is 0xFFFFFFFF.
	DWORD dwSubclass11;   // Waypoint subclass for auto-routes. User waypoint is 0xFFFFFFFF.
	WORD  wWptSubclass;   // 0x0000 for user waypoint.
	DWORD dwSubclass3;    // Waypoint subclassing for auto-routes. User waypoint is 0xFFFFFFFF.

	// Lat/Lon, in arcs (180/2^31 deg).
	LONG  lY;
	LONG  lX;

	// The altitude.
	BYTE  btHasAltitude;  // 0 - no altitude, 1 - has altitude
	double dblAltitude;   // In meters

	// The comment.
	char strDescription [1]; // Zero-terminated.
};

struct CMpsWaypoint3 {
//	BYTE  bt0;            // zero

	// The proximity.
	BYTE   btHasProximity;// 0 - no proximity, 1 - has proximity
	double dblProximity;  // In meters.

	// How to diplay:
	// 0x0 - symbol, 0x1 - symbol & name, 0x2 - symbol and description
	DWORD dwShow;  

	// The color:
	// 0 - unknown, 1 - black, 2 - dk red, 3 - dk green, 4 - dk yellow,
	// 5 - dk blue, 6 - dk magenta, 7 - dk cyan, 8 - lt gray, 9 - dk gray, 0x0A - red
	// 0x0B - green, 0x0C - yellow, 0x0D - blue, 0x0E - magenta, 0x0F - cyan, 0x10 -  white
	DWORD dwColor; 

	// The type:
	// 0x00 - marina,        0x0A - residence,      0x0e - Skull & Crossbones,
    // 0x12 - waypoint,      0x15 - navaid (amber),
	// 0x25 - boat ramp,     0x26 - campground,     0x2d - parking area, 0x2e - park,
	// 0x32 - swimming area, 0x38 - car,            0x3e - truck stop,
	// 0x4c - car repair,
	// 0x50 - museum,        0x5e - building,       0x5d - bridge
	// 0x69 - Forest,        0x6a - summit,         0x6b - airport,      0x6c - heliport
	DWORD dwType;  

	DWORD dw0;            // zero

	// The depth.
	BYTE  btHasDepth;     // 0 - no depth, 1 - has depth
	double dblDepth;      // In 10x meters

	WORD  wUnknown0;      // 0x0000

	// ?? For autorouting-generated routes
	DWORD dwLegTime;
	char strRoutingDirections [1];
};

	//
	// Route.
	//

struct CMpsRouteHdr : public CMpsRecordHdr {
	// The label.
	char strName [1];     // Null-terminated.
};

	//
	// Track.
	//

struct CMpsTrackHdr : public CMpsRecordHdr {
	// The label.
	char strName [1];     // Null-terminated.
};

struct CMpsTrackPoint {
	// Lat/lon, in arcs.
	LONG  lY;
	LONG  lX;

	// The altitude.
	BYTE  btHasAltitude;  // 1 - has altitude, 0 - not defined
	double dblAltitude;   // In meters.

	// The time stamp.
	BYTE  btHasTime;      // 0 - no time info, 1 - has time info (NOTE: compressed tracks have no time)
	DWORD dwDateTime;     // In seconds elapsed since 1 Jan 1970

	// The depth.
	BYTE  btHasDepth;     // 0 - no depth, 1 - has depth
	double dblDepth;      // In meters.
};

struct CMpsTrack2 {
	BYTE  btDisplayOnGPS; // 1 - display, 0 - hide
	DWORD dwColor;        // 0 - black etc (see above for waypoint)

	// The number of points in the track.
	DWORD dwPoints;
	CMpsTrackPoint points [1];
};

	//
	// Map reference.
	//

struct CMpsMapHdr : public CMpsRecordHdr {
	WORD  wProductID;
	WORD  wFamilyID;
    DWORD dwImgID;

    char strProductName [1];
//	char strMapName [1];
//	char strAreaName [1];
};

# ifdef _MSC_VER
#	pragma pack (pop)
# endif


# endif // __MpsFile_H_
